package com.ruyuan2020.im.nioExample;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class Server {
    // 定义属性
    private Selector selector;
    private ServerSocketChannel ssChannel;
    private static final int PORT = 9999;

    // 构造器，初始化工作
    public Server() {
        try {
            // 1、获取通道
            ssChannel = ServerSocketChannel.open();
            // 2、切换为非阻塞模式
            ssChannel.configureBlocking(false);
            // 3、绑定连接的端口
            ssChannel.bind(new InetSocketAddress(PORT));
            // 4、获取选择器Selector
            selector = Selector.open();
            // 5、将通道注册到选择器上，并指定监听接收事件
            ssChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 监听方法
    public void listen() {
        System.out.println("监听线程: " + Thread.currentThread().getName());
        try {
            while (selector.select() > 0) {
                System.out.println("开始一轮事件处理~~~");
                // 6、获取选择器中所有注册的已经就绪好的事件
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while (it.hasNext()) {
                    // 提取当前事件
                    SelectionKey sk = it.next();
                    // 7、判断事件类型
                    if (sk.isAcceptable()) {
                        // 8、接收就绪事件处理
                        handleAccept(sk);
                    } else if (sk.isReadable()) {
                        // 9、读就绪事件处理
                        handleRead(sk);
                    }
                    // 处理完毕后移除当前事件
                    it.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 异常处理或清理工作
        }
    }

    // 处理接收就绪事件
    private void handleAccept(SelectionKey key) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept();
        clientChannel.configureBlocking(false);
        // 将客户端通道注册到选择器，并监听读事件
        clientChannel.register(selector, SelectionKey.OP_READ);
        System.out.println(clientChannel.getRemoteAddress() + " 上线 ");
    }

    // 处理读就绪事件
    private void handleRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int count = channel.read(buffer);
        if (count > 0) {
            buffer.flip();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            String msg = new String(bytes);
            System.out.println("From 客户端: " + msg);
            // 转发消息给其他客户端（排除自己）
            sendInfoToOtherClients(msg, channel);
        }
    }

    // 转发消息给其他客户端
    private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息中...");
        for (SelectionKey key : selector.keys()) {
            Channel targetChannel = key.channel();
            if (targetChannel instanceof SocketChannel && targetChannel != self) {
                SocketChannel dest = (SocketChannel) targetChannel;
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                dest.write(buffer);
            }
        }
    }

    public static void main(String[] args) {
        // 创建服务器对象并启动监听
        Server server = new Server();
        server.listen();
    }
}
